home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows 95 / Programming Windows 95.iso / code / CHAP17 / SHOWPOP2.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-01  |  8.5 KB  |  273 lines

  1. /*------------------------------------------
  2.    SHOWPOP2.C -- DDEML Client using DDEPOP2
  3.                  (c) Charles Petzold, 1996
  4.   ------------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <ddeml.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "showpop.h"
  11.  
  12. #define WM_USER_INITIATE (WM_USER + 1)
  13. #define DDE_TIMEOUT      3000
  14.  
  15. LRESULT  CALLBACK WndProc     (HWND, UINT, WPARAM, LPARAM) ;
  16. HDDEDATA CALLBACK DdeCallback (UINT, UINT, HCONV, HSZ, HSZ,
  17.                                HDDEDATA, DWORD, DWORD) ;
  18.  
  19. char  szAppName[] = "ShowPop2" ;
  20. DWORD idInst ;
  21. HCONV hConv ;
  22. HWND  hwnd ;
  23.  
  24. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  25.                     PSTR szCmdLine, int iCmdShow)
  26.      {
  27.      MSG        msg ;
  28.      WNDCLASSEX wndclass ;
  29.  
  30.      wndclass.cbSize        = sizeof (wndclass) ;
  31.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  32.      wndclass.lpfnWndProc   = WndProc ;
  33.      wndclass.cbClsExtra    = 0 ;
  34.      wndclass.cbWndExtra    = 0 ;
  35.      wndclass.hInstance     = hInstance ;
  36.      wndclass.hIcon         = LoadIcon (hInstance, szAppName) ;
  37.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  38.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  39.      wndclass.lpszMenuName  = NULL ;
  40.      wndclass.lpszClassName = szAppName ;
  41.      wndclass.hIconSm       = LoadIcon (hInstance, szAppName) ;
  42.  
  43.      RegisterClassEx (&wndclass) ;
  44.  
  45.      hwnd = CreateWindow (szAppName, "DDEML Client - US Population",
  46.                           WS_OVERLAPPEDWINDOW,
  47.                           CW_USEDEFAULT, CW_USEDEFAULT,
  48.                           CW_USEDEFAULT, CW_USEDEFAULT,
  49.                           NULL, NULL, hInstance, NULL) ;
  50.  
  51.      ShowWindow (hwnd, iCmdShow) ;
  52.      UpdateWindow (hwnd) ;
  53.  
  54.                // Initialize for using DDEML
  55.  
  56.  
  57.      if (DdeInitialize (&idInst, (PFNCALLBACK) &DdeCallback,
  58.                         APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0L))
  59.           {
  60.           MessageBox (hwnd, "Could not initialize client!",
  61.                       szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  62.  
  63.           DestroyWindow (hwnd) ;
  64.           return FALSE ;
  65.           }
  66.  
  67.                // Start things going
  68.  
  69.      SendMessage (hwnd, WM_USER_INITIATE, 0, 0L) ;
  70.  
  71.      while (GetMessage (&msg, NULL, 0, 0))
  72.           {
  73.           TranslateMessage (&msg) ;
  74.           DispatchMessage (&msg) ;
  75.           }
  76.  
  77.                // Uninitialize DDEML
  78.  
  79.      DdeUninitialize (idInst) ;
  80.  
  81.      return msg.wParam ;
  82.      }
  83.  
  84. HDDEDATA CALLBACK DdeCallback (UINT iType, UINT iFmt, HCONV hConv,
  85.                                HSZ hsz1, HSZ hsz2, HDDEDATA hData,
  86.                                DWORD dwData1, DWORD dwData2)
  87.      {
  88.      char szItem[10], szPopulation[16] ;
  89.      int  i ;
  90.  
  91.      switch (iType)
  92.           {
  93.           case XTYP_ADVDATA :       // hsz1  = topic
  94.                                     // hsz2  = item
  95.                                     // hData = data
  96.  
  97.                     // Check for matching format and data item
  98.  
  99.                if (iFmt != CF_TEXT)
  100.                     return DDE_FNOTPROCESSED ;
  101.  
  102.                DdeQueryString (idInst, hsz2, szItem, sizeof (szItem), 0) ;
  103.  
  104.                for (i = 0 ; i < NUM_STATES ; i++)
  105.                     if (strcmp (szItem, pop[i].szAbb) == 0)
  106.                          break ;
  107.  
  108.                if (i >= NUM_STATES)
  109.                     return DDE_FNOTPROCESSED ;
  110.  
  111.                     // Store the data and invalidate the window
  112.  
  113.                DdeGetData (hData, (unsigned char *) szPopulation,
  114.                            sizeof (szPopulation), 0) ;
  115.  
  116.                pop[i].lPop = atol (szPopulation) ;
  117.  
  118.                InvalidateRect (hwnd, NULL, FALSE) ;
  119.  
  120.                return (HDDEDATA) DDE_FACK ;
  121.  
  122.           case XTYP_DISCONNECT :
  123.                hConv = NULL ;
  124.  
  125.                MessageBox (hwnd, "The server has disconnected.",
  126.                            szAppName, MB_ICONASTERISK | MB_OK) ;
  127.  
  128.                return NULL ;
  129.           }
  130.  
  131.      return NULL ;
  132.      }
  133.  
  134. LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  135.      {
  136.      static char  szService[] = "DdePop2",
  137.                   szTopic[]   = "US_Population" ;
  138.      static long  cxChar, cyChar ;
  139.      char         szBuffer[24] ;
  140.      HDC          hdc ;
  141.      HSZ          hszService, hszTopic, hszItem ;
  142.      PAINTSTRUCT  ps ;
  143.      int          i ;
  144.      long         x, y ;
  145.      TEXTMETRIC   tm ;
  146.  
  147.      switch (iMsg)
  148.           {
  149.           case WM_CREATE :
  150.                hdc = GetDC (hwnd) ;
  151.                GetTextMetrics (hdc, &tm) ;
  152.                cxChar = tm.tmAveCharWidth ;
  153.                cyChar = tm.tmHeight + tm.tmExternalLeading ;
  154.                ReleaseDC (hwnd, hdc) ;
  155.  
  156.                return 0 ;
  157.  
  158.           case WM_USER_INITIATE :
  159.  
  160.                          // Try connecting
  161.  
  162.                hszService = DdeCreateStringHandle (idInst, szService, 0) ;
  163.                hszTopic   = DdeCreateStringHandle (idInst, szTopic,   0) ;
  164.  
  165.                hConv = DdeConnect (idInst, hszService, hszTopic, NULL) ;
  166.  
  167.                          // If that doesn't work, load server
  168.  
  169.                if (hConv == NULL)
  170.                     {
  171.                     WinExec (szService, SW_SHOWMINNOACTIVE) ;
  172.  
  173.                     hConv = DdeConnect (idInst, hszService, hszTopic, NULL) ;
  174.                     }
  175.  
  176.                          // Free the string handles
  177.  
  178.                DdeFreeStringHandle (idInst, hszService) ;
  179.                DdeFreeStringHandle (idInst, hszTopic) ;
  180.  
  181.                          // If still not connected, display message box
  182.  
  183.                if (hConv == NULL)
  184.                     {
  185.                     MessageBox (hwnd, "Cannot connect with DDEPOP2.EXE!",
  186.                                 szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  187.  
  188.                     return 0 ;
  189.                     }
  190.  
  191.                          // Request notification
  192.  
  193.                for (i = 0 ; i < NUM_STATES ; i++)
  194.                     {
  195.                     hszItem = DdeCreateStringHandle (idInst, pop[i].szAbb, 0) ;
  196.  
  197.                     DdeClientTransaction (NULL, 0, hConv, hszItem, CF_TEXT,
  198.                                           XTYP_ADVSTART | XTYPF_ACKREQ,
  199.                                           DDE_TIMEOUT, NULL) ;
  200.  
  201.                     DdeFreeStringHandle (idInst, hszItem) ;
  202.                     }
  203.  
  204.                if (i < NUM_STATES)
  205.                     {
  206.                     MessageBox (hwnd, "Failure on WM_DDE_ADVISE!",
  207.                                 szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  208.                     }
  209.  
  210.                return 0 ;
  211.  
  212.           case WM_PAINT :
  213.                hdc = BeginPaint (hwnd, &ps) ;
  214.  
  215.                for (i = 0 ; i < NUM_STATES ; i++)
  216.                     {
  217.                     if (i < (NUM_STATES + 1) / 2)
  218.                          {
  219.                          x = cxChar ;
  220.                          y = i * cyChar ;
  221.                          }
  222.                     else
  223.                          {
  224.                          x = 44 * cxChar ;
  225.                          y = (i - (NUM_STATES + 1) / 2) * cyChar ;
  226.                          }
  227.  
  228.                     TextOut (hdc, x, y, szBuffer,
  229.                              wsprintf (szBuffer, "%-20s",
  230.                                        (PSTR) pop[i].szState)) ;
  231.  
  232.                     x += 36 * cxChar ;
  233.  
  234.                     SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;
  235.  
  236.                     TextOut (hdc, x, y, szBuffer,
  237.                              wsprintf (szBuffer, "%10ld", pop[i].lPop)) ;
  238.  
  239.                     SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
  240.                     }
  241.  
  242.                EndPaint (hwnd, &ps) ;
  243.                return 0 ;
  244.  
  245.           case WM_CLOSE :
  246.                if (hConv == NULL)
  247.                     break ;
  248.  
  249.                          // Stop the advises
  250.  
  251.                for (i = 0 ; i < NUM_STATES ; i++)
  252.                     {
  253.                     hszItem = DdeCreateStringHandle (idInst, pop[i].szAbb, 0) ;
  254.  
  255.                     DdeClientTransaction (NULL, 0, hConv, hszItem, CF_TEXT,
  256.                                           XTYP_ADVSTOP, DDE_TIMEOUT, NULL) ;
  257.  
  258.                     DdeFreeStringHandle (idInst, hszItem) ;
  259.                     }
  260.  
  261.                          // Disconnect the conversation
  262.  
  263.                DdeDisconnect (hConv) ;
  264.  
  265.                break ;             // for default processing
  266.  
  267.           case WM_DESTROY :
  268.                PostQuitMessage (0) ;
  269.                return 0 ;
  270.           }
  271.      return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
  272.      }
  273.